﻿using System;
using System.Threading;
using System.Threading.Tasks;

namespace 事件锁
{
    class Program
    {
        /*****
         * AutoResetEvent 就类似 我们去火车站坐火车检票一样
         * true 表示终止，闸机没有票
         * false 表示非终止，闸机有票
         * 
         * ******/
        static AutoResetEvent autoEvent=new AutoResetEvent(false);

        /****
         * ManualResetEvent  就类似，有人看守的火车道路
         * 如果有火车马上来了，栅栏会放下来阻止行人通过，
         * 如果火车走了，栅栏就放开，行人可以通过了，
         * true 没有阻止行人
         * false 阻止行人通过
         * 
         * *****/
        static ManualResetEvent manualEvent = new ManualResetEvent(false);
        /***
         * 信号量
         * 通过int数值来控制线程个数
         * 第一个参数表示线程数量
         * *****/
        static Semaphore semaphore = new Semaphore(1, 10);

        /***
         * 互斥锁
         * ****/
        static Mutex mutex = new Mutex();

        /***
         * 上面的锁都是继承了 WaitHandle，都有 WaitOne  方法
         * 
         * ******/



        static int num = 0;
        static void Main(string[] args)
        {
            // TestAutoResetEvetn();
            //TestManualEvent();
            //TestSemaphore();
            TestMutex();


            Console.Read(); 
        }



        public static void TestMutex()
        {

            for (int i = 0; i < 5; i++)
            {
                Task.Factory.StartNew(() =>
                {
                    Run4();
                });
            }


        }

        public static void Run4()
        {
            for (int i = 0; i < 100; i++)
            {
                try
                {
                    mutex.WaitOne();
                    Console.WriteLine(num++);
                    mutex.ReleaseMutex();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                finally
                {
                }
            }
        }


        public static void TestSemaphore()
        {

            for (int i = 0; i < 5; i++)
            {
                Task.Factory.StartNew(() =>
                {
                    Run3();
                });
            }
           

        }

        public static void Run3()
        {
            for (int i = 0; i < 100; i++)
            {
                try
                {
                    semaphore.WaitOne();
                    Console.WriteLine(num++);
                    semaphore.Release();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                finally
                {
                }
            }
        }




        public static void TestManualEvent()
        {

            for (int i = 0; i < 5; i++)
            {
                Task.Factory.StartNew(() =>
                {
                    Run2();
                });
            }
            //一开始 false 阻止行人的，
            Thread.Sleep(5000);
            //5s 后堆积了一堆行人，这个时候，放开栅栏，让行人通过，
            // 行人就是一群飞快的通过
            manualEvent.Set();

        }

        public static void Run2()
        {
            for (int i = 0; i < 100; i++)
            {
                try
                {
                    manualEvent.WaitOne();
                    Console.WriteLine(num++);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                finally
                {
                }
            }
        }


        public static void TestAutoResetEvetn()
        {
            //autoEvent.WaitOne();// 插入票时，发现里面有票  false，
            //Console.WriteLine("验证通过");
            //autoEvent.Set();// 取出票

            for (int i = 0; i < 5; i++)
            {
                Task.Factory.StartNew(() =>
                {
                    Run();
                });
            }
        }

        public static void Run()
        {
            for (int i = 0; i < 100; i++)
            {
                try
                {
                    autoEvent.WaitOne();
                    Console.WriteLine(num++);
                    autoEvent.Set();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                finally
                {
                }
            }
        }


    }
}
